﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Autofac;
using Autofac.Core.Lifetime;
using Microsoft.AspNetCore.Http;

namespace Ubiquity.Web.Filters
{
    public static class ContainerManager
    {
        private static IContainer _container;

        public static void SetContainer(IContainer container)
        {
            _container = container;
        }

        public static IContainer Container
        {
            get { return _container; }
        }

        public static T Resolve<T>(string key = "", ILifetimeScope scope = null) where T : class
        {
            if (scope == null)
            {
                //no scope specified
                scope = Scope();
            }
            if (string.IsNullOrEmpty(key))
            {
                return scope.Resolve<T>();
            }
            return scope.ResolveKeyed<T>(key);
        }

        public static object Resolve(Type type, ILifetimeScope scope = null)
        {
            if (scope == null)
            {
                //no scope specified
                scope = Scope();
            }
            return scope.Resolve(type);
        }

        public static T[] ResolveAll<T>(string key = "", ILifetimeScope scope = null)
        {
            if (scope == null)
            {
                //no scope specified
                scope = Scope();
            }
            if (string.IsNullOrEmpty(key))
            {
                return scope.Resolve<IEnumerable<T>>().ToArray();
            }
            return scope.ResolveKeyed<IEnumerable<T>>(key).ToArray();
        }

        public static T ResolveUnregistered<T>(ILifetimeScope scope = null) where T : class
        {
            return ResolveUnregistered(typeof(T), scope) as T;
        }

        public static object ResolveUnregistered(Type type, ILifetimeScope scope = null)
        {
            if (scope == null)
            {
                //no scope specified
                scope = Scope();
            }
            var constructors = type.GetConstructors();
            foreach (var constructor in constructors)
            {
                try
                {
                    var parameters = constructor.GetParameters();
                    var parameterInstances = new List<object>();
                    foreach (var parameter in parameters)
                    {
                        var service = Resolve(parameter.ParameterType, scope);
                        if (service == null) throw new ArgumentException("Unkown dependency");
                        parameterInstances.Add(service);
                    }
                    return Activator.CreateInstance(type, parameterInstances.ToArray());
                }
                catch (ArgumentException)
                {

                }
            }
            throw new ArgumentException("在所有的依赖项中，未找到合适的构造函数。");
        }

        public static bool TryResolve(Type serviceType, ILifetimeScope scope, out object instance)
        {
            if (scope == null)
            {
                //no scope specified
                scope = Scope();
            }
            return scope.TryResolve(serviceType, out instance);
        }

        public static bool IsRegistered(Type serviceType, ILifetimeScope scope = null)
        {
            if (scope == null)
            {
                //no scope specified
                scope = Scope();
            }
            return scope.IsRegistered(serviceType);
        }

        public static object ResolveOptional(Type serviceType, ILifetimeScope scope = null)
        {
            if (scope == null)
            {
                //no scope specified
                scope = Scope();
            }
            return scope.ResolveOptional(serviceType);
        }

        public static ILifetimeScope Scope()
        {
            try
            {
                //if (HttpContext.Current != null)
                //    return AutofacDependencyResolver.Current.RequestLifetimeScope;

                //when such lifetime scope is returned, you should be sure that it'll be disposed once used (e.g. in schedule tasks)
                return Container.BeginLifetimeScope(MatchingScopeLifetimeTags.RequestLifetimeScopeTag);
            }
            catch (Exception)
            {
                //we can get an exception here if RequestLifetimeScope is already disposed
                //for example, requested in or after "Application_EndRequest" handler
                //but note that usually it should never happen

                //when such lifetime scope is returned, you should be sure that it'll be disposed once used (e.g. in schedule tasks)
                return Container.BeginLifetimeScope(MatchingScopeLifetimeTags.RequestLifetimeScopeTag);
            }
        }
    }

    /// <summary>
    /// IOCConfig
    /// </summary>
    public class IOCConfig
    {
        /// <summary>
        /// RegisterAll
        /// </summary>
        public static void RegisterAll()
        {
            var iocBuilder = new Autofac.ContainerBuilder();

            ////todo:为了能编译到web目录，并且发布方便，才在web项目中引用repository项目，在代码中不要直接使用之
            //iocBuilder.RegisterModule<RIS.Infrastructure.RegisterModule>();
            //iocBuilder.RegisterModule<RIS.Biz.RegisterModule>();
            //iocBuilder.RegisterModule<RIS.Repository.RegisterModule>();

            //iocBuilder.Register((c, p) => new WebWorkContext(p.Named<string>("userToken")))
            //    .As<RIS.Biz.Core.IWorkContext>()
            //    .InstancePerLifetimeScope();


            //iocBuilder.RegisterControllers(Assembly.GetExecutingAssembly());

            //iocBuilder.RegisterApiControllers(Assembly.GetExecutingAssembly());

            //iocBuilder.RegisterModelBinders(Assembly.GetExecutingAssembly());
            //iocBuilder.RegisterModelBinderProvider();
            //iocBuilder.RegisterModule<AutofacWebTypesModule>();
            //var config = GlobalConfiguration.Configuration;
            //iocBuilder.RegisterWebApiFilterProvider(config);
            IContainer iocContainer = iocBuilder.Build();
            //config.DependencyResolver = new AutofacWebApiDependencyResolver(iocContainer);
            //System.Web.Mvc.DependencyResolver.SetResolver(new AutofacDependencyResolver(iocContainer));


            ContainerManager.SetContainer(iocContainer);
        }
    }

    //// 注意: 有关启用 IIS6 或 IIS7 经典模式的说明，
    //// 请访问 http://go.microsoft.com/?LinkId=9394801
    ///// <summary>
    ///// MvcApplication
    ///// </summary>
    //public class MvcApplication : System.Web.HttpApplication
    //{
    //    /// <summary>
    //    /// 程序启动入口
    //    /// </summary>
    //    protected void Application_Start()
    //    {
    //        IOCConfig.RegisterAll();

    //        AreaRegistration.RegisterAllAreas();

    //        WebApiConfig.Register(GlobalConfiguration.Configuration);
    //        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    //        RouteConfig.RegisterRoutes(RouteTable.Routes);
    //        BundleConfig.RegisterBundles(BundleTable.Bundles);
    //    }
    //}
}